home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / amitcp / kern / uipc_socket.c < prev    next >
C/C++ Source or Header  |  1993-12-18  |  32KB  |  1,305 lines

  1. RCS_ID_C="$Id: uipc_socket.c,v 1.28 1993/12/18 15:28:09 jraja Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * HISTORY
  8.  * $Log: uipc_socket.c,v $
  9.  * Revision 1.28  1993/12/18  15:28:09  jraja
  10.  * Disabled code using M_EOR, unless USE_M_EOR is defined.
  11.  *
  12.  * Revision 1.27  1993/11/17  12:12:48  jraja
  13.  * Added check for the SB_SEL flag to sohasoutofband() to prevent superfluous
  14.  * calls to selwakeup().
  15.  *
  16.  * Revision 1.26  1993/11/17  09:20:33  jraja
  17.  * Fixed selwakeup bug in sohasoutofband(), there was mixture of net2 & bsdss
  18.  * -style selwakeup usage.
  19.  *
  20.  * Revision 1.25  1993/06/04  11:16:15  jraja
  21.  * Fixes for first public release.
  22.  *
  23.  * Revision 1.24  1993/05/17  01:07:47  ppessi
  24.  * Changed RCS version.
  25.  *
  26.  * Revision 1.23  1993/04/28  13:42:48  too
  27.  * Fixed setting of linger value in getsockopt()
  28.  *
  29.  * Revision 1.22  93/04/26  11:54:49  11:54:49  too (Tomi Ollila)
  30.  * Changed include paths of amiga_api.h, amiga_libcallentry.h and amiga_raf.h
  31.  * from kern to api
  32.  * 
  33.  * Revision 1.21  93/04/24  22:45:52  22:45:52  jraja (Jarno Tapio Rajahalme)
  34.  * Removed Define for USECLUSTERS
  35.  * 
  36.  * Revision 1.20  93/04/24  17:52:15  17:52:15  jraja (Jarno Tapio Rajahalme)
  37.  * Changed MCLBYTES to mbconf.mclbytes.
  38.  * 
  39.  * Revision 1.19  93/04/12  00:37:56  00:37:56  jraja (Jarno Tapio Rajahalme)
  40.  * Added #include <kern/amiga_includes.h> for Signal().
  41.  * 
  42.  * Revision 1.18  93/04/12  00:29:11  00:29:11  jraja (Jarno Tapio Rajahalme)
  43.  * Added signalling of task (SIGURG).
  44.  * 
  45.  * Revision 1.17  93/04/11  22:28:37  22:28:37  jraja (Jarno Tapio Rajahalme)
  46.  * Removed one extra argument from call to pr_usrreq.
  47.  * Added parenthesis around &&'s inside ||'s.
  48.  * 
  49.  * Revision 1.16  93/04/06  15:16:08  15:16:08  jraja (Jarno Tapio Rajahalme)
  50.  * Changed spl function return value storage to spl_t,
  51.  * changed bcopys and bzeros to aligned and/or const when possible,
  52.  * added inclusion of conf.h to every .c file.
  53.  * 
  54.  * Revision 1.15  93/03/21  16:59:37  16:59:37  jraja (Jarno Tapio Rajahalme)
  55.  * Changed linger time to seconds. Removed obsolete test on timeout value for
  56.  * send/receive timeout (was checked to fit in a short, but since the timeouts are
  57.  * now timeval's the check is not needed.
  58.  * 
  59.  * Revision 1.14  93/03/19  14:14:56  14:14:56  too (Tomi Ollila)
  60.  * Code changes at night 17-18 March 1993
  61.  * 
  62.  * Revision 1.13  93/03/17  12:06:35  12:06:35  jraja (Jarno Tapio Rajahalme)
  63.  * Fixed tsleep() call to find socket base if necessary and to give NULL
  64.  * timeout if timeval is all zeroes.
  65.  * 
  66.  * Revision 1.12  93/03/16  19:47:16  19:47:16  too (Tomi Ollila)
  67.  * uses multible mbufs (broken)
  68.  * 
  69.  * Revision 1.11  93/03/13  17:13:06  17:13:06  ppessi (Pekka Pessi)
  70.  * Fixed bugs with variable initializations. Works with UDP.
  71.  * 
  72.  * Revision 1.10  93/03/05  03:26:23  03:26:23  ppessi (Pekka Pessi)
  73.  * Compiles with SASC. Initial test version.
  74.  * 
  75.  * Revision 1.9  93/03/04  10:57:17  10:57:17  jraja (Jarno Tapio Rajahalme)
  76.  * Added prototype inclusion for kern/uipc_domain_protos_.h.h
  77.  * 
  78.  * Revision 1.8  93/03/04  09:53:45  09:53:45  jraja (Jarno Tapio Rajahalme)
  79.  * Removed some redundant includes.
  80.  * 
  81.  * Revision 1.7  93/02/27  11:03:55  11:03:55  too (Tomi Ollila)
  82.  * Added Prototypes
  83.  * 
  84.  * Revision 1.6  93/02/25  13:01:48  13:01:48  too (Tomi Ollila)
  85.  * Added static inlines, sys/cdefs etc.
  86.  * 
  87.  * Revision 1.5  93/02/24  18:14:47  18:14:47  too (Tomi Ollila)
  88.  * Compiles. support for so_linger and sb_timeo as struct timeval type added.
  89.  * 
  90.  * Revision 1.4  93/02/23  11:37:56  11:37:56  too (Tomi Ollila)
  91.  * Made AMITCP combatible, not compiled yet
  92.  * 
  93.  * Revision 1.3  93/01/09  12:56:26  12:56:26  jraja (Jarno Tapio Rajahalme)
  94.  * Added #ifdef USECLUSTERS to disable cluster dependant code.
  95.  * 
  96.  * Revision 1.2  92/11/20  15:14:49  15:14:49  jraja (Jarno Tapio Rajahalme)
  97.  * Added #ifndef AMITCP's to make this compile.
  98.  * 
  99.  * Revision 1.1  92/11/19  12:07:27  12:07:27  jraja (Jarno Tapio Rajahalme)
  100.  * Initial revision
  101.  * 
  102.  *
  103.  */
  104.  
  105. /* 
  106.  * Mach Operating System
  107.  * Copyright (c) 1992 Carnegie Mellon University
  108.  * All Rights Reserved.
  109.  * 
  110.  * Permission to use, copy, modify and distribute this software and its
  111.  * documentation is hereby granted, provided that both the copyright
  112.  * notice and this permission notice appear in all copies of the
  113.  * software, derivative works or modified versions, and any portions
  114.  * thereof, and that both notices appear in supporting documentation.
  115.  * 
  116.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  117.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  118.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  119.  * 
  120.  * Carnegie Mellon requests users of this software to return to
  121.  * 
  122.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  123.  *  School of Computer Science
  124.  *  Carnegie Mellon University
  125.  *  Pittsburgh PA 15213-3890
  126.  * 
  127.  * any improvements or extensions that they make and grant Carnegie Mellon 
  128.  * the rights to redistribute these changes.
  129.  */
  130. /*
  131.  * HISTORY
  132.  * Log:    uipc_socket.c,v
  133.  * Revision 2.1  92/04/21  17:12:32  rwd
  134.  * BSDSS
  135.  * 
  136.  *
  137.  */
  138.  
  139. /*
  140.  * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
  141.  * All rights reserved.
  142.  *
  143.  * Redistribution and use in source and binary forms, with or without
  144.  * modification, are permitted provided that the following conditions
  145.  * are met:
  146.  * 1. Redistributions of source code must retain the above copyright
  147.  *    notice, this list of conditions and the following disclaimer.
  148.  * 2. Redistributions in binary form must reproduce the above copyright
  149.  *    notice, this list of conditions and the following disclaimer in the
  150.  *    documentation and/or other materials provided with the distribution.
  151.  * 3. All advertising materials mentioning features or use of this software
  152.  *    must display the following acknowledgement:
  153.  *    This product includes software developed by the University of
  154.  *    California, Berkeley and its contributors.
  155.  * 4. Neither the name of the University nor the names of its contributors
  156.  *    may be used to endorse or promote products derived from this software
  157.  *    without specific prior written permission.
  158.  *
  159.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  160.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  161.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  162.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  163.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  164.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  165.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  166.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  167.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  168.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  169.  * SUCH DAMAGE.
  170.  *
  171.  *    @(#)uipc_socket.c    7.28 (Berkeley) 5/4/91
  172.  */
  173.  
  174. #include <conf.h>
  175.  
  176. #include <sys/param.h>
  177. #include <sys/systm.h>
  178. #include <sys/malloc.h>
  179. #include <sys/mbuf.h>
  180. #include <sys/domain.h>
  181. #include <sys/kernel.h>
  182. #include <sys/protosw.h>
  183. #include <sys/socket.h>
  184. #include <sys/socketvar.h>
  185.  
  186. #include <sys/synch.h>
  187. #include <api/amiga_api.h>
  188.  
  189. #include <kern/amiga_includes.h>
  190.  
  191. #include <kern/uipc_socket_protos.h>
  192. #include <kern/uipc_socket2_protos.h>
  193. #include <kern/uipc_domain_protos.h>
  194. #include <kern/amiga_select_protos.h>
  195.  
  196. /*
  197.  * Socket operation routines.
  198.  * These routines are called by the routines in
  199.  * sys_socket.c or from a system process, and
  200.  * implement the semantics of socket operations by
  201.  * switching out to the protocol specific routines.
  202.  */
  203. int
  204. socreate(dom, aso, type, proto)
  205.         int dom;
  206.         struct socket **aso;
  207.     register int type;
  208.     int proto;
  209. {
  210. #ifndef AMITCP
  211.         struct proc *p = (struct proc*)cthread_data(cthread_self());
  212. #endif /* AMITCP */
  213.     register struct protosw *prp;
  214.     register struct socket *so;
  215.     register int error;
  216.  
  217.     if (proto)
  218.         prp = pffindproto(dom, proto, type);
  219.     else
  220.         prp = pffindtype(dom, type);
  221.     if (prp == 0)
  222.         return (EPROTONOSUPPORT);
  223.     if (prp->pr_type != type)
  224.         return (EPROTOTYPE);
  225.     MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_WAIT);
  226.     aligned_bzero_const((caddr_t)so, sizeof(*so));
  227.     so->so_type = type;
  228. #ifndef AMITCP
  229.     if (p->p_ucred->cr_uid == 0)
  230. #endif /* AMITCP */
  231.         so->so_state = SS_PRIV; /* all sockets have the force  now */
  232.     so->so_proto = prp;
  233.     error =
  234.         (*prp->pr_usrreq)(so, PRU_ATTACH,
  235.         (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0);
  236.     if (error) {
  237.         so->so_state |= SS_NOFDREF;
  238.         sofree(so);
  239.         return (error);
  240.     }
  241.     *aso = so;
  242.     return (0);
  243. }
  244.  
  245. int
  246. sobind(so, nam)
  247.     struct socket *so;
  248.     struct mbuf *nam;
  249. {
  250.     spl_t s = splnet();
  251.     int error;
  252.  
  253.     error =
  254.         (*so->so_proto->pr_usrreq)(so, PRU_BIND,
  255.         (struct mbuf *)0, nam, (struct mbuf *)0);
  256.     splx(s);
  257.     return (error);
  258. }
  259.  
  260. int
  261. solisten(so, backlog)
  262.     register struct socket *so;
  263.     int backlog;
  264. {
  265.     spl_t s = splnet(), error;
  266.  
  267.     error =
  268.         (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
  269.         (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
  270.     if (error) {
  271.         splx(s);
  272.         return (error);
  273.     }
  274.     if (so->so_q == 0)
  275.         so->so_options |= SO_ACCEPTCONN;
  276.     if (backlog < 0)
  277.         backlog = 0;
  278.     so->so_qlimit = min(backlog, SOMAXCONN);
  279.     splx(s);
  280.     return (0);
  281. }
  282.  
  283. void
  284. sofree(so)
  285.     register struct socket *so;
  286. {
  287.  
  288.     if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
  289.         return;
  290.     if (so->so_head) {
  291.         if (!soqremque(so, 0) && !soqremque(so, 1))
  292.             panic("sofree dq");
  293.         so->so_head = 0;
  294.     }
  295.     sbrelease(&so->so_snd);
  296.     sorflush(so);
  297.     FREE(so, M_SOCKET);
  298. }
  299.  
  300. /*
  301.  * Close a socket on last file table reference removal.
  302.  * Initiate disconnect if connected.
  303.  * Free socket when disconnect complete.
  304.  */
  305. int
  306. soclose(so)
  307.     register struct socket *so;
  308. {
  309.     spl_t s = splnet();        /* conservative */
  310.     int error = 0;
  311.     struct SocketBase *socketBase;
  312.     struct timeval *timeo;
  313.  
  314.     if (so->so_options & SO_ACCEPTCONN) {
  315.         while (so->so_q0)
  316.             (void) soabort(so->so_q0);
  317.         while (so->so_q)
  318.             (void) soabort(so->so_q);
  319.     }
  320.     if (so->so_pcb == 0)
  321.         goto discard;
  322.     if (so->so_state & SS_ISCONNECTED) {
  323.         if ((so->so_state & SS_ISDISCONNECTING) == 0) {
  324.             error = sodisconnect(so);
  325.             if (error)
  326.                 goto drop;
  327.         }
  328.         if (so->so_options & SO_LINGER) {
  329.             if ((so->so_state & SS_ISDISCONNECTING) &&
  330.                 (so->so_state & SS_NBIO))
  331.                 goto drop;
  332.             /*
  333.              * Find socket base for the tsleep()
  334.              */
  335.             if ((socketBase = FindSocketBase(FindTask(NULL)))
  336.                 == NULL)
  337.                 goto drop; /* couldn't find */
  338.             timeo = (so->so_linger.tv_sec 
  339.                  || so->so_linger.tv_usec) ?
  340.                      &so->so_linger : NULL;
  341.             while (so->so_state & SS_ISCONNECTED)
  342.                 if (error = tsleep(socketBase,
  343.                            (caddr_t)&so->so_timeo,
  344.                            netcls, timeo))
  345.                     break;
  346.         }
  347.     }
  348. drop:
  349.     if (so->so_pcb) {
  350.         int error2 =
  351.             (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
  352.             (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
  353.         if (error == 0)
  354.             error = error2;
  355.     }
  356. discard:
  357.     if (so->so_state & SS_NOFDREF)
  358.         panic("soclose: NOFDREF");
  359.     so->so_state |= SS_NOFDREF;
  360.     sofree(so);
  361.     splx(s);
  362.     return (error);
  363. }
  364.  
  365. /*
  366.  * Must be called at splnet...
  367.  */
  368. int
  369. soabort(so)
  370.     struct socket *so;
  371. {
  372.  
  373.     return (
  374.         (*so->so_proto->pr_usrreq)(so, PRU_ABORT,
  375.         (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
  376. }
  377.  
  378. int
  379. soaccept(so, nam)
  380.     register struct socket *so;
  381.     struct mbuf *nam;
  382. {
  383.     spl_t s = splnet();
  384.     int error;
  385.  
  386.     if ((so->so_state & SS_NOFDREF) == 0)
  387.         panic("soaccept: !NOFDREF");
  388.     so->so_state &= ~SS_NOFDREF;
  389.     error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
  390.         (struct mbuf *)0, nam, (struct mbuf *)0);
  391.     splx(s);
  392.     return (error);
  393. }
  394.  
  395. int
  396. soconnect(so, nam)
  397.     register struct socket *so;
  398.     struct mbuf *nam;
  399. {
  400.     spl_t s;
  401.     int error;
  402.  
  403.     if (so->so_options & SO_ACCEPTCONN)
  404.         return (EOPNOTSUPP);
  405.     s = splnet();
  406.     /*
  407.      * If protocol is connection-based, can only connect once.
  408.      * Otherwise, if connected, try to disconnect first.
  409.      * This allows user to disconnect by connecting to, e.g.,
  410.      * a null address.
  411.      */
  412.     if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
  413.         ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
  414.         (error = sodisconnect(so))))
  415.         error = EISCONN;
  416.     else
  417.         error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
  418.             (struct mbuf *)0, nam, (struct mbuf *)0);
  419.     splx(s);
  420.     return (error);
  421. }
  422.  
  423. #ifndef AMITCP
  424. soconnect2(so1, so2)
  425.     register struct socket *so1;
  426.     struct socket *so2;
  427. {
  428.     spl_t s = splnet();
  429.     int error;
  430.  
  431.     error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
  432.         (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0);
  433.     splx(s);
  434.     return (error);
  435. }
  436. #endif
  437.  
  438. int
  439. sodisconnect(so)
  440.     register struct socket *so;
  441. {
  442.     spl_t s = splnet();
  443.     int error;
  444.  
  445.     if ((so->so_state & SS_ISCONNECTED) == 0) {
  446.         error = ENOTCONN;
  447.         goto bad;
  448.     }
  449.     if (so->so_state & SS_ISDISCONNECTING) {
  450.         error = EALREADY;
  451.         goto bad;
  452.     }
  453.     error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
  454.         (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
  455. bad:
  456.     splx(s);
  457.     return (error);
  458. }
  459.  
  460. #ifdef AMITCP
  461. /*
  462.  * uioread() replaces uiomove() in sosend
  463.  */
  464.  
  465. static inline void uioread(caddr_t cp, int n, struct uio *uio)
  466. {
  467.   struct iovec *iov;
  468.   u_int cnt;
  469.  
  470.   while (n > 0 && uio->uio_resid) {
  471.     iov = uio->uio_iov;
  472.     cnt = iov->iov_len;
  473.     if (cnt == 0) {
  474.       uio->uio_iov++;
  475.       uio->uio_iovcnt--;
  476.       continue;
  477.     }
  478.     if (cnt > n)
  479.       cnt = n;
  480.  
  481.     bcopy(iov->iov_base, cp, cnt); /* wrong direction //pp */
  482.  
  483.     iov->iov_base += cnt;
  484.     iov->iov_len -= cnt;
  485.     uio->uio_resid -= cnt;
  486.     cp += cnt;
  487.     n -= cnt;
  488.   }
  489. }
  490.  
  491. #endif /* AMITCP */
  492.  
  493.  
  494. /*
  495.  * Send on a socket.
  496.  * If send must go all at once and message is larger than
  497.  * send buffering, then hard error.
  498.  * Lock against other senders.
  499.  * If must go all at once and not enough room now, then
  500.  * inform user that this would block and do nothing.
  501.  * Otherwise, if nonblocking, send as much as possible.
  502.  * The data to be sent is described by "uio" if nonzero,
  503.  * otherwise by the mbuf chain "top" (which must be null
  504.  * if uio is not).  Data provided in mbuf chain must be small
  505.  * enough to send all at once.
  506.  *
  507.  * Returns nonzero on error, timeout or signal; callers
  508.  * must check for short counts if EINTR/ERESTART are returned.
  509.  * Data and control buffers are freed on return.
  510.  */
  511. int
  512. sosend(so, addr, uio, top, control, flags)
  513.     register struct socket *so;
  514.     struct mbuf *addr;
  515.     struct uio *uio;
  516.     struct mbuf *top;
  517.     struct mbuf *control;
  518.     int flags;
  519. {
  520. #ifndef AMITCP /* proc not defined */
  521.         struct proc *p = (struct proc*)cthread_data(cthread_self());
  522. #endif /* AMITCP */
  523.     struct mbuf **mp;
  524.     register struct mbuf *m;
  525.     register long space, len, resid;
  526.     int clen = 0, error, dontroute, mlen;
  527.     spl_t s;
  528.     int atomic = sosendallatonce(so) || top;
  529.  
  530.     if (uio)
  531.         resid = uio->uio_resid;
  532.     else
  533.         resid = top->m_pkthdr.len;
  534.  
  535.     dontroute =
  536.         (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
  537.         (so->so_proto->pr_flags & PR_ATOMIC);
  538. #ifndef AMITCP
  539.     p->p_stats->p_ru.ru_msgsnd++;
  540. #endif /* AMITCP */
  541.     if (control)
  542.         clen = control->m_len;
  543. #define    snderr(errno)    { error = errno; splx(s); goto release; }
  544.  
  545. restart:
  546.     if (error = sblock(&so->so_snd, uio->uio_procp))
  547.         goto out;
  548.     do {
  549.         s = splnet();
  550.         if (so->so_state & SS_CANTSENDMORE)
  551.             snderr(EPIPE);
  552.         if (so->so_error)
  553.             snderr(so->so_error);
  554.         if ((so->so_state & SS_ISCONNECTED) == 0) {
  555.             if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
  556.                 if ((so->so_state & SS_ISCONFIRMING) == 0 &&
  557.                     !(resid == 0 && clen != 0))
  558.                     snderr(ENOTCONN);
  559.             } else if (addr == 0)
  560.                 snderr(EDESTADDRREQ);
  561.         }
  562.         space = sbspace(&so->so_snd);
  563.         if (flags & MSG_OOB)
  564.             space += 1024;
  565.         if (space < resid + clen &&
  566.             (atomic || space < so->so_snd.sb_lowat || space < clen)) {
  567.             if ((atomic && resid > so->so_snd.sb_hiwat) ||
  568.                 clen > so->so_snd.sb_hiwat)
  569.                 snderr(EMSGSIZE);
  570.             if (so->so_state & SS_NBIO)
  571.                 snderr(EWOULDBLOCK);
  572.             sbunlock(&so->so_snd);
  573.             error = sbwait(&so->so_snd, uio->uio_procp);
  574.             splx(s);
  575.             if (error)
  576.                 goto out;
  577.             goto restart;
  578.         }
  579.         splx(s);
  580.         mp = ⊤
  581.         space -= clen;
  582.         do {
  583.             if (uio == NULL) {
  584.             /*
  585.              * Data is prepackaged in "top".
  586.              */
  587.             resid = 0;
  588. #ifdef USE_M_EOR
  589.             if (flags & MSG_EOR)
  590.                 top->m_flags |= M_EOR;
  591. #endif
  592.             } else do {
  593.             if (top == 0) {
  594.                 MGETHDR(m, M_WAIT, MT_DATA);
  595.                 mlen = MHLEN;
  596.                 m->m_pkthdr.len = 0;
  597.                 m->m_pkthdr.rcvif = (struct ifnet *)0;
  598.             } else {
  599.                 MGET(m, M_WAIT, MT_DATA);
  600.                 mlen = MLEN;
  601.             }
  602.             if (resid >= MINCLSIZE && space >= mbconf.mclbytes) {
  603.                 MCLGET(m, M_WAIT);
  604.                 if ((m->m_flags & M_EXT) == 0)
  605.                     goto nopages;
  606.                 mlen = mbconf.mclbytes;
  607. #ifdef    MAPPED_MBUFS
  608.                 len = min(mbconf.mclbytes, resid);
  609. #else
  610.                 if (top == 0) {
  611.                     len = min(mbconf.mclbytes - max_hdr, resid);
  612.                     m->m_data += max_hdr;
  613.                 } else
  614.                     len = min(mbconf.mclbytes, resid);
  615. #endif
  616.                 space -= mbconf.mclbytes;
  617.             } else
  618.               {
  619. nopages:
  620.                 len = min(min(mlen, resid), space);
  621.                 space -= len;
  622.                 /*
  623.                  * For datagram protocols, leave room
  624.                  * for protocol headers in first mbuf.
  625.                  */
  626.                 if (atomic && top == 0 && len < mlen)
  627.                     MH_ALIGN(m, len);
  628.             }
  629.             uioread(mtod(m, caddr_t), (int)len, uio);
  630.             resid = uio->uio_resid;
  631.             m->m_len = len;
  632.             *mp = m;
  633.             top->m_pkthdr.len += len;
  634.             if (error)
  635.                 goto release;
  636.             mp = &m->m_next;
  637.             if (resid <= 0) {
  638. #ifdef USE_M_EOR
  639.                 if (flags & MSG_EOR)
  640.                     top->m_flags |= M_EOR;
  641. #endif
  642.                 break;
  643.             }
  644.             } 
  645. #if defined(AMITCP) && 0
  646.             /* all the data in 1 mbuf chain */
  647.             while (space > 0);
  648. #else
  649.             while (space > 0 && atomic);
  650. #endif
  651.             if (dontroute)
  652.                 so->so_options |= SO_DONTROUTE;
  653.             s = splnet();                /* XXX */
  654.             error = (*so->so_proto->pr_usrreq)(so,
  655.             (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
  656.             top, addr, control);
  657.             splx(s);
  658.             if (dontroute)
  659.                 so->so_options &= ~SO_DONTROUTE;
  660.             clen = 0;
  661.             control = 0;
  662.             top = 0;
  663.             mp = ⊤
  664.             if (error)
  665.             goto release;
  666.         } while (resid && space > 0);
  667.     } while (resid);
  668.  
  669. release:
  670.     sbunlock(&so->so_snd);
  671. out:
  672.     if (top)
  673.         m_freem(top);
  674.     if (control)
  675.         m_freem(control);
  676.     return (error);
  677. }
  678.  
  679.  
  680. #ifdef AMITCP
  681. /*
  682.  * uiowrite() replaces uiomove() in soreceive
  683.  */
  684.  
  685. static inline void uiowrite(caddr_t cp, int n, struct uio *uio)
  686. {
  687.   struct iovec *iov;
  688.   u_int cnt;
  689.  
  690.   while (n > 0 && uio->uio_resid) {
  691.     iov = uio->uio_iov;
  692.     cnt = iov->iov_len;
  693.     if (cnt == 0) {
  694.       uio->uio_iov++;
  695.       uio->uio_iovcnt--;
  696.       continue;
  697.     }
  698.     if (cnt > n)
  699.       cnt = n;
  700.  
  701.     bcopy(cp, iov->iov_base, cnt);
  702.  
  703.     iov->iov_base += cnt;
  704.     iov->iov_len -= cnt;
  705.     uio->uio_resid -= cnt;
  706.     cp += cnt;
  707.     n -= cnt;
  708.   }
  709. }
  710. #endif /* AMITCP */
  711. /*
  712.  * Implement receive operations on a socket.
  713.  * We depend on the way that records are added to the sockbuf
  714.  * by sbappend*.  In particular, each record (mbufs linked through m_next)
  715.  * must begin with an address if the protocol so specifies,
  716.  * followed by an optional mbuf or mbufs containing ancillary data,
  717.  * and then zero or more mbufs of data.
  718.  * In order to avoid blocking network interrupts for the entire time here,
  719.  * we splx() while doing the actual copy to user space.
  720.  * Although the sockbuf is locked, new data may still be appended,
  721.  * and thus we must maintain consistency of the sockbuf during that time.
  722.  *
  723.  * The caller may receive the data as a single mbuf chain by supplying
  724.  * an mbuf **mp0 for use in returning the chain.  The uio is then used
  725.  * only for the count in uio_resid.
  726.  */
  727. int
  728. soreceive(so, paddr, uio, mp0, controlp, flagsp)
  729.     register struct socket *so;
  730.     struct mbuf **paddr;
  731.     struct uio *uio;
  732.     struct mbuf **mp0;
  733.     struct mbuf **controlp;
  734.     int *flagsp;
  735. {
  736. #ifndef AMITCP
  737.         struct proc *p = (struct proc*)cthread_data(cthread_self());
  738. #endif
  739.     register struct mbuf *m, **mp;
  740.     register int flags, len, error, offset;
  741.     spl_t s;
  742.     struct protosw *pr = so->so_proto;
  743.     struct mbuf *nextrecord;
  744.     int moff, type;
  745.  
  746.     mp = mp0;
  747.     if (paddr)
  748.         *paddr = 0;
  749.     if (controlp)
  750.         *controlp = 0;
  751.     if (flagsp)
  752.         flags = *flagsp &~ MSG_EOR;
  753.     else
  754.         flags = 0;
  755.     if (flags & MSG_OOB) {
  756.         m = m_get(M_WAIT, MT_DATA);
  757.         error = (*pr->pr_usrreq)(so, PRU_RCVOOB,
  758.             m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0);
  759.         if (error)
  760.             goto bad;
  761.  
  762.         do {
  763.             uiowrite(mtod(m, caddr_t),
  764.                 (int) min(uio->uio_resid, m->m_len), uio);
  765.             m = m_free(m);
  766.         } while (uio->uio_resid && error == 0 && m);
  767.  
  768. bad:
  769.         if (m)
  770.             m_freem(m);
  771.         return (error);
  772.     }
  773.     if (mp)
  774.         *mp = (struct mbuf *)0;
  775.  
  776.     if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
  777.         (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
  778.             (struct mbuf *)0, (struct mbuf *)0);
  779.  
  780.  
  781. restart:
  782.     if (error = sblock(&so->so_rcv, uio->uio_procp))
  783.         return (error);
  784.     s = splnet();
  785.  
  786.     m = so->so_rcv.sb_mb;
  787.     /*
  788.      * If we have less data than requested, block awaiting more
  789.      * (subject to any timeout) if:
  790.      *   1. the current count is less than the low water mark, or
  791.      *   2. MSG_WAITALL is set, and it is possible to do the entire
  792.      *    receive operation at once if we block (resid <= hiwat).
  793.      * If MSG_WAITALL is set but resid is larger than the receive buffer,
  794.      * we have to do the receive in sections, and thus risk returning
  795.      * a short count if a timeout or signal occurs after we start.
  796.      */
  797.  
  798.     while (m == 0 || (so->so_rcv.sb_cc < uio->uio_resid &&
  799.               (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
  800.                ((flags & MSG_WAITALL)
  801.                 && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
  802.               m->m_nextpkt == 0)) {
  803. #if DIAGNOSTIC
  804.             if (m == 0 && so->so_rcv.sb_cc)
  805.             panic("receive 1");
  806. #endif
  807.         if (so->so_error) {
  808.             if (m)
  809.                 break;
  810.             error = so->so_error;
  811.             if ((flags & MSG_PEEK) == 0)
  812.                 so->so_error = 0;
  813.             goto release;
  814.         }
  815.         if (so->so_state & SS_CANTRCVMORE) {
  816.             if (m)
  817.                 break;
  818.             else
  819.                 goto release;
  820.         }
  821.         for (; m; m = m->m_next)
  822.             if (m->m_type == MT_OOBDATA
  823. #ifdef USE_M_EOR
  824.   || (m->m_flags & M_EOR)
  825. #endif
  826.                 ) {
  827.                 m = so->so_rcv.sb_mb;
  828.                 goto dontblock;
  829.             }
  830.         if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
  831.             (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
  832.             error = ENOTCONN;
  833.             goto release;
  834.         }
  835.  
  836.         if (uio->uio_resid == 0)
  837.             goto release;
  838.  
  839.         if (so->so_state & SS_NBIO) {
  840.             error = EWOULDBLOCK;
  841.             goto release;
  842.         }
  843.         sbunlock(&so->so_rcv);
  844.         error = sbwait(&so->so_rcv, uio->uio_procp);
  845.         splx(s);
  846.         if (error)
  847.             return (error);
  848.         goto restart;
  849.     }
  850. dontblock:
  851. #ifndef AMITCP
  852.     p->p_stats->p_ru.ru_msgrcv++;
  853. #endif
  854.     nextrecord = m->m_nextpkt;
  855.     if (pr->pr_flags & PR_ADDR) {
  856. #if DIAGNOSTIC
  857.         if (m->m_type != MT_SONAME)
  858.             panic("receive 1a");
  859. #endif
  860.         if (flags & MSG_PEEK) {
  861.             if (paddr)
  862.                 *paddr = m_copy(m, 0, m->m_len);
  863.             m = m->m_next;
  864.         } else {
  865.             sbfree(&so->so_rcv, m);
  866.             if (paddr) {
  867.                 *paddr = m;
  868.                 so->so_rcv.sb_mb = m->m_next;
  869.                 m->m_next = 0;
  870.                 m = so->so_rcv.sb_mb;
  871.             } else {
  872.                 MFREE(m, so->so_rcv.sb_mb);
  873.                 m = so->so_rcv.sb_mb;
  874.             }
  875.         }
  876.     }
  877.     while (m && m->m_type == MT_CONTROL && error == 0) {
  878.         if (flags & MSG_PEEK) {
  879.             if (controlp)
  880.                 *controlp = m_copy(m, 0, m->m_len);
  881.             m = m->m_next;
  882.         } else {
  883.             sbfree(&so->so_rcv, m);
  884.             if (controlp) {
  885.                 if (pr->pr_domain->dom_externalize &&
  886.                     mtod(m, struct cmsghdr *)->cmsg_type ==
  887.                     SCM_RIGHTS)
  888.                    error = (*pr->pr_domain->dom_externalize)(m);
  889.                 *controlp = m;
  890.                 so->so_rcv.sb_mb = m->m_next;
  891.                 m->m_next = 0;
  892.                 m = so->so_rcv.sb_mb;
  893.             } else {
  894.                 MFREE(m, so->so_rcv.sb_mb);
  895.                 m = so->so_rcv.sb_mb;
  896.             }
  897.         }
  898.         if (controlp)
  899.             controlp = &(*controlp)->m_next;
  900.     }
  901.     if (m) {
  902.         if ((flags & MSG_PEEK) == 0)
  903.             m->m_nextpkt = nextrecord;
  904.         type = m->m_type;
  905.         if (type == MT_OOBDATA)
  906.             flags |= MSG_OOB;
  907.     }
  908.     moff = 0;
  909.     offset = 0;
  910.     while (m &&  uio->uio_resid > 0 &&  error == 0) {
  911.         if (m->m_type == MT_OOBDATA) {
  912.             if (type != MT_OOBDATA)
  913.                 break;
  914.         } else if (type == MT_OOBDATA)
  915.             break;
  916. #if DIAGNOSTIC
  917.         else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
  918.             panic("receive 3");
  919. #endif
  920.         so->so_state &= ~SS_RCVATMARK;
  921.  
  922.         len = uio->uio_resid;
  923.  
  924.         if (so->so_oobmark && len > so->so_oobmark - offset)
  925.             len = so->so_oobmark - offset;
  926.         if (len > m->m_len - moff)
  927.             len = m->m_len - moff;
  928.         /*
  929.          * If mp is set, just pass back the mbufs.
  930.          * Otherwise copy them out via the uio, then free.
  931.          * Sockbuf must be consistent here (points to current mbuf,
  932.          * it points to next record) when we drop priority;
  933.          * we must note any additions to the sockbuf when we
  934.          * block interrupts again.
  935.          */
  936.  
  937.         if (mp == 0) {
  938.             splx(s);
  939.             uiowrite(mtod(m, caddr_t) + moff, (int)len, uio);
  940.             s = splnet();
  941.         } else
  942.             uio->uio_resid -= len;
  943.  
  944.         if (len == m->m_len - moff) {
  945. #ifdef USE_M_EOR
  946.             if (m->m_flags & M_EOR)
  947.                 flags |= MSG_EOR;
  948. #endif
  949.             if (flags & MSG_PEEK) {
  950.                 m = m->m_next;
  951.                 moff = 0;
  952.             } else {
  953.                 nextrecord = m->m_nextpkt;
  954.                 sbfree(&so->so_rcv, m);
  955.                 if (mp) {
  956.                     *mp = m;
  957.                     mp = &m->m_next;
  958.                     so->so_rcv.sb_mb = m = m->m_next;
  959.                     *mp = (struct mbuf *)0;
  960.                 } else {
  961.                     MFREE(m, so->so_rcv.sb_mb);
  962.                     m = so->so_rcv.sb_mb;
  963.                 }
  964.                 if (m)
  965.                     m->m_nextpkt = nextrecord;
  966.             }
  967.         } else {
  968.             if (flags & MSG_PEEK)
  969.                 moff += len;
  970.             else {
  971.                 if (mp)
  972.                     *mp = m_copym(m, 0, len, M_WAIT);
  973.                 m->m_data += len;
  974.                 m->m_len -= len;
  975.                 so->so_rcv.sb_cc -= len;
  976.             }
  977.         }
  978.         if (so->so_oobmark) {
  979.             if ((flags & MSG_PEEK) == 0) {
  980.                 so->so_oobmark -= len;
  981.                 if (so->so_oobmark == 0) {
  982.                     so->so_state |= SS_RCVATMARK;
  983.                     break;
  984.                 }
  985.             } else
  986.                 offset += len;
  987.         }
  988.         if (flags & MSG_EOR)
  989.             break;
  990.         /*
  991.          * If the MSG_WAITALL flag is set (for non-atomic socket),
  992.          * we must not quit until "uio->uio_resid == 0" or an error
  993.          * termination.  If a signal/timeout occurs, return
  994.          * with a short count but without error.
  995.          * Keep sockbuf locked against other readers.
  996.          */
  997.         while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
  998.                !sosendallatonce(so)) {
  999.             if (so->so_error || so->so_state & SS_CANTRCVMORE)
  1000.                 break;
  1001.             error = sbwait(&so->so_rcv, uio->uio_procp);
  1002.             if (error) {
  1003.                 sbunlock(&so->so_rcv);
  1004.                 splx(s);
  1005.                 return (0);
  1006.             }
  1007.             if (m = so->so_rcv.sb_mb)
  1008.                 nextrecord = m->m_nextpkt;
  1009.         }
  1010.     }
  1011.     if ((flags & MSG_PEEK) == 0) {
  1012.         if (m == 0)
  1013.             so->so_rcv.sb_mb = nextrecord;
  1014.         else if (pr->pr_flags & PR_ATOMIC) {
  1015.             flags |= MSG_TRUNC;
  1016.             (void) sbdroprecord(&so->so_rcv);
  1017.         }
  1018.         if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
  1019.             (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
  1020.                 (struct mbuf *)flags, /* (struct mbuf *)0, */
  1021.                 (struct mbuf *)0); /* BUG! One extra arg! */
  1022.     }
  1023.     if (flagsp)
  1024.         *flagsp |= flags;
  1025. release:
  1026.     sbunlock(&so->so_rcv);
  1027.     splx(s);
  1028.     return (error);
  1029. }
  1030.  
  1031. int
  1032. soshutdown(so, how)
  1033.     register struct socket *so;
  1034.     register int how;
  1035. {
  1036.     register struct protosw *pr = so->so_proto;
  1037.  
  1038.     how++; /* now how: 1 - no receives, 2 - no sends, 3 - no either */
  1039.     if (how & 1)
  1040.       sorflush(so);
  1041.     if (how & 2)
  1042.       return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 
  1043.                    (struct mbuf *)0, (struct mbuf *)0));
  1044.     return (0);
  1045. }
  1046.  
  1047. void
  1048. sorflush(so)
  1049.     register struct socket *so;
  1050. {
  1051.     register struct sockbuf *sb = &so->so_rcv;
  1052.     register struct protosw *pr = so->so_proto;
  1053.     register spl_t s;
  1054.     struct sockbuf asb;
  1055.  
  1056.     sb->sb_flags |= SB_NOINTR;
  1057.     (void) sblock(sb, NULL);
  1058.     s = splimp();
  1059.     socantrcvmore(so);
  1060.     sbunlock(sb);
  1061.     asb = *sb;
  1062.     aligned_bzero_const((caddr_t)sb, sizeof (*sb));
  1063.     splx(s);
  1064.     if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
  1065.         (*pr->pr_domain->dom_dispose)(asb.sb_mb);
  1066.     sbrelease(&asb);
  1067. }
  1068.  
  1069. /*
  1070.  * in some fields of socket structure previous short fields of ticks are
  1071.  * changed to struct timeval fields. (actually so_linger and sb_timeo)
  1072.  * sosetopt() and sogetopt() does transformations needed for those.
  1073.  */
  1074.  
  1075. int
  1076. sosetopt(so, level, optname, m0)
  1077.     register struct socket *so;
  1078.     int level, optname;
  1079.     struct mbuf *m0;
  1080. {
  1081.     int error = 0;
  1082.     register struct mbuf *m = m0;
  1083.  
  1084.     if (level != SOL_SOCKET) {
  1085.         if (so->so_proto && so->so_proto->pr_ctloutput)
  1086.             return ((*so->so_proto->pr_ctloutput)
  1087.                   (PRCO_SETOPT, so, level, optname, &m0));
  1088.         error = ENOPROTOOPT;
  1089.     } else {
  1090.         switch (optname) {
  1091.  
  1092.         case SO_LINGER:
  1093.             if (m == NULL || m->m_len != sizeof (struct linger)) {
  1094.                 error = EINVAL;
  1095.                 goto bad;
  1096.             }
  1097.             {
  1098.               int val = mtod(m, struct linger *)->l_linger;
  1099. #ifdef AMITCP
  1100.               /*
  1101.                * l_linger is in seconds
  1102.                */
  1103.               so->so_linger.tv_sec = val;
  1104.               so->so_linger.tv_usec = 0;
  1105. #else
  1106.               so->so_linger.tv_sec = val / hz;
  1107.               so->so_linger.tv_usec = (val % hz) * tick;
  1108. #endif
  1109.             }
  1110.             /* fall thru... */
  1111.  
  1112.         case SO_DEBUG:
  1113.         case SO_KEEPALIVE:
  1114.         case SO_DONTROUTE:
  1115.         case SO_USELOOPBACK:
  1116.         case SO_BROADCAST:
  1117.         case SO_REUSEADDR:
  1118.         case SO_OOBINLINE:
  1119.             if (m == NULL || m->m_len < sizeof (int)) {
  1120.                 error = EINVAL;
  1121.                 goto bad;
  1122.             }
  1123.             if (*mtod(m, int *))
  1124.                 so->so_options |= optname;
  1125.             else
  1126.                 so->so_options &= ~optname;
  1127.             break;
  1128.  
  1129.         case SO_SNDBUF:
  1130.         case SO_RCVBUF:
  1131.         case SO_SNDLOWAT:
  1132.         case SO_RCVLOWAT:
  1133.             if (m == NULL || m->m_len < sizeof (int)) {
  1134.                 error = EINVAL;
  1135.                 goto bad;
  1136.             }
  1137.             switch (optname) {
  1138.  
  1139.             case SO_SNDBUF:
  1140.             case SO_RCVBUF:
  1141.                 if (sbreserve(optname == SO_SNDBUF ?
  1142.                     &so->so_snd : &so->so_rcv,
  1143.                     (u_long) *mtod(m, int *)) == 0) {
  1144.                     error = ENOBUFS;
  1145.                     goto bad;
  1146.                 }
  1147.                 break;
  1148.  
  1149.             case SO_SNDLOWAT:
  1150.                 so->so_snd.sb_lowat = *mtod(m, int *);
  1151.                 break;
  1152.             case SO_RCVLOWAT:
  1153.                 so->so_rcv.sb_lowat = *mtod(m, int *);
  1154.                 break;
  1155.             }
  1156.             break;
  1157.  
  1158.         case SO_SNDTIMEO:
  1159.         case SO_RCVTIMEO:
  1160.             {
  1161.             struct timeval *tv;
  1162.  
  1163.             if (m == NULL || m->m_len < sizeof (*tv)) {
  1164.                 error = EINVAL;
  1165.                 goto bad;
  1166.             }
  1167.             tv = mtod(m, struct timeval *);
  1168.  
  1169.             switch (optname) {
  1170.  
  1171.             case SO_SNDTIMEO:
  1172.                 so->so_snd.sb_timeo = *tv;
  1173.                 break;
  1174.             case SO_RCVTIMEO:
  1175.                 so->so_rcv.sb_timeo = *tv;
  1176.                 break;
  1177.             }
  1178.             break;
  1179.             }
  1180.  
  1181.         default:
  1182.             error = ENOPROTOOPT;
  1183.             break;
  1184.         }
  1185.     }
  1186. bad:
  1187.     if (m)
  1188.         (void) m_free(m);
  1189.     return (error);
  1190. }
  1191.  
  1192. int
  1193. sogetopt(so, level, optname, mp)
  1194.     register struct socket *so;
  1195.     int level, optname;
  1196.     struct mbuf **mp;
  1197. {
  1198.     register struct mbuf *m;
  1199.  
  1200.     if (level != SOL_SOCKET) {
  1201.         if (so->so_proto && so->so_proto->pr_ctloutput) {
  1202.             return ((*so->so_proto->pr_ctloutput)
  1203.                   (PRCO_GETOPT, so, level, optname, mp));
  1204.         } else
  1205.             return (ENOPROTOOPT);
  1206.     } else {
  1207.         m = m_get(M_WAIT, MT_SOOPTS);
  1208.         m->m_len = sizeof (int);
  1209.  
  1210.         switch (optname) {
  1211.  
  1212.         case SO_LINGER:
  1213.             m->m_len = sizeof (struct linger);
  1214.             mtod(m, struct linger *)->l_onoff =
  1215.                 so->so_options & SO_LINGER;
  1216.             mtod(m, struct linger *)->l_linger =
  1217. #ifndef AMITCP
  1218.               so->so_linger.tv_sec * hz +
  1219.                 so->so_linger.tv_usec / tick;
  1220. #else
  1221.             /*
  1222.              * l_linger is in seconds
  1223.              */
  1224.               so->so_linger.tv_sec;
  1225. #endif            
  1226.             break;
  1227.  
  1228.         case SO_USELOOPBACK:
  1229.         case SO_DONTROUTE:
  1230.         case SO_DEBUG:
  1231.         case SO_KEEPALIVE:
  1232.         case SO_REUSEADDR:
  1233.         case SO_BROADCAST:
  1234.         case SO_OOBINLINE:
  1235.             *mtod(m, int *) = so->so_options & optname;
  1236.             break;
  1237.  
  1238.         case SO_TYPE:
  1239.             *mtod(m, int *) = so->so_type;
  1240.             break;
  1241.  
  1242.         case SO_ERROR:
  1243.             *mtod(m, int *) = so->so_error;
  1244.             so->so_error = 0;
  1245.             break;
  1246.  
  1247.         case SO_SNDBUF:
  1248.             *mtod(m, int *) = so->so_snd.sb_hiwat;
  1249.             break;
  1250.  
  1251.         case SO_RCVBUF:
  1252.             *mtod(m, int *) = so->so_rcv.sb_hiwat;
  1253.             break;
  1254.  
  1255.         case SO_SNDLOWAT:
  1256.             *mtod(m, int *) = so->so_snd.sb_lowat;
  1257.             break;
  1258.  
  1259.         case SO_RCVLOWAT:
  1260.             *mtod(m, int *) = so->so_rcv.sb_lowat;
  1261.             break;
  1262.  
  1263.         case SO_SNDTIMEO:
  1264.         case SO_RCVTIMEO:
  1265.             {
  1266.             struct timeval *tv= (optname == SO_SNDTIMEO ?
  1267.                  &so->so_snd.sb_timeo : &so->so_rcv.sb_timeo);
  1268.  
  1269.             m->m_len = sizeof(struct timeval);
  1270.             mtod(m, struct timeval *)->tv_sec = tv->tv_sec;
  1271.             mtod(m, struct timeval *)->tv_usec = tv->tv_usec;
  1272.             break;
  1273.             }
  1274.  
  1275.         default:
  1276.             (void)m_free(m);
  1277.             return (ENOPROTOOPT);
  1278.         }
  1279.         *mp = m;
  1280.         return (0);
  1281.     }
  1282. }
  1283.  
  1284. void
  1285. sohasoutofband(so)
  1286.     register struct socket *so;
  1287. {
  1288. #ifdef AMITCP
  1289.     if (so->so_pgid)
  1290.         Signal(so->so_pgid->thisTask, so->so_pgid->sigUrgMask);
  1291. #else
  1292.     struct proc *p;
  1293.  
  1294.     if (so->so_pgid < 0)
  1295.         gsignal(-so->so_pgid, SIGURG);
  1296.     else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
  1297.         psignal(p, SIGURG);
  1298. #endif
  1299.     if (so->so_rcv.sb_flags & SB_SEL) {
  1300.         so->so_rcv.sb_flags &= ~SB_SEL; /* do not notify us any more */
  1301.         selwakeup(&so->so_rcv.sb_sel);
  1302.     }
  1303. }
  1304.  
  1305.